.TITLE EMDRV .IDENT /01.02/ ; ; Copyright (c) 1995-1999 by Mentec, Inc., U.S.A. ; All rights reserved ; ; ; THIS SOFTWARE IS FURNISHED UNDER A LICENSE AND MAY BE USED ; OR COPIED ONLY IN ACCORDANCE WITH THE TERMS OF SUCH LICENSE. ; ; VERSION 01.02 ; ; P. J. CARR 25-AUG-81 ; ; MODIFIED BY: ; ; P. J. BEZEREDI 14-SEP-81 ; ; PB264 -- RESTORE I/O PACKET ADDRESS AFTER WRITE CHECK ; DETERMINATION CODE. ; ; P. J. BEZEREDI 22-OCT-81 ; ; PB269 -- RETURN IE.SZE ERROR FOR NON-EXISTANT UNIT. ; ; ; RH11-ML11 MEMORY SYSTEM DRIVER ; ; MACRO LIBRARY CALLS ; .MCALL HWDDF$,PKTDF$ HWDDF$ ;DEFINE HARDWARE REGISTERS PKTDF$ ;DEFINE I/O PACKET OFFSETS ; ; EQUATED SYMBOLS ; ADR= 10 ;ADDRESS BITS SET UP (1=YES) SEL= 20 ;PORT SELECT WAIT (1=WAITING) RETRY= 8. ;ERROR RETRY COUNT ; ; ML11 DEVICE REGISTER OFFSETS ; MLCS1= 0 ;CONTROL AND STATUS REGISTER MLWC= 2 ;WORD COUNT REGISTER MLBA= 4 ;BUS ADDRESS REGISTER MLDA= 6 ;TRACK/SECTOR ADDRESS MLCS2= 10 ;SECOND STATUS REGISTER MLDS= 12 ;DRIVE STATUS REGISTER MLER= 14 ;ERROR REGISTER MLAS= 16 ;ATTENTION SUMMARY REGISTER ; ; MLCS1 BIT ASSIGNMENTS ; TRE= 40000 ;TRANSFER ERROR ; ; LOCAL DATA ; ; CONTROLLER IMPURE DATA TABLES (INDEXED BY CONTROLLER NUMBER) ; RTTBL: .BLKW M$$L11 ;RETRY COUNT FOR CURRENT OPERATION PRMSV: .BLKW M$$L11*5 ;PARAMETER SAVE AREA FOR ERROR RECOVERY ;AND WRITE CHECK FUNCTION ; ; DRIVER DISPATCH TABLE ; DDT$ EM,M$$L11 ;GENERATE DISPATCH TABLE ;+ ; **-EMINI-RH11-ML11 MEMORY SYSTEM INITIATOR ; ; THIS ROUTINE IS ENTERED FROM THE QUEUE I/O DIRECTIVE WHEN AN I/O ; REQUEST IS QUEUED AND AT THE END OF A PREVIOUS I/O OPERATION TO ; PROPAGATE THE EXECUTION OF THE DRIVER. IF THE SPECIFIED UNIT IS ; NOT BUSY, THEN AN ATTEMPT IS MADE TO DEQUEUE THE NEXT I/O REQUEST, ; ELSE A RETURN TO THE CALLER IS EXECUTED. IF THE DEQUEUE ATTEMPT IS ; SUCCESSFUL, THEN THE NEXT I/O OPERATION IS INITIATED FOLLOWED BY A ; RETURN TO THE CALLER. ; ; INPUTS: ; ; R5=ADDRESS OF THE UCB OF THE UNIT TO BE INITIATED ; ; OUTPUTS: ; ; IF THE SPECIFIED UNIT IS NOT BUSY AND AN I/O REQUEST IS WAITING ; TO BE PROCESSED, THEN THE NEXT REQUEST IS DEQUEUED AND THE I/O ; OPERATION IS INITIATED. ;- .ENABL LSB EMINI: GTPKT$ EM,M$$L11 ;GET NEXT I/O PACKET TO PROCESS ; ; THE FOLLOWING ARGUMENTS ARE RETURNED BY $GTPKT: ; ; R1=ADDRESS OF THE I/O REQUEST PACKET ; R2=PHYSICAL UNIT NUMBER OF THE REQUEST UCB ; R3=CONTROLLER INDEX ; R4=ADDRESS OF THE STATUS CONTROL BLOCK ; R5=ADDRESS OF THE UCB OF THE UNIT TO BE INITIATED ; ; RH11-ML11 MEMORY SYSTEM I/O REQUEST PACKET FORMAT: ; ; WD. 00 -- I/O QUEUE THREAD WORD ; WD. 01 -- REQUEST PRIORITY, EVENT FLAG NUMBER ; WD. 02 -- ADDRESS OF THE TCB OF THE REQUESTOR TASK ; WD. 03 -- POINTER TO SECOND LUN WORD IN REQUESTOR TASK HEADER ; WD. 04 -- FIRST LUN WORD IN REQUESTORS TASK HEADER ; WD. 05 -- I/O FUNCTION CODE (IO.RLB OR IO.WLB) ; WD. 06 -- VIRTUAL ADDRESS OF I/O STATUS BLOCK ; WD. 07 -- RELOCATION BIAS OF I/O STATUS BLOCK ; WD. 10 -- I/O STATUS BLOCK ADDRESS (DISPLACEMENT + 140000) ; WD. 11 -- VIRTUAL ADDRESS OF AST SERVICE ROUTINE ; WD. 12 -- MEMORY EXTENSION BITS (BITS 4 AND 5) OF I/O TRANSFER ; WD. 13 -- BUFFER ADDRESS OF I/O TRANSFER ; WD. 14 -- NUMBER OF BYTES TO BE TRANSFERRED ; WD. 15 -- NOT USED ; WD. 16 -- BITS <0:7> = HIGH LBN, BITS <8:15> NOT USED ; WD. 17 -- LOW LBN OF I/O REQUEST ; WD. 20 -- RELOCATION BIAS OF REGISTER BLOCK ELSE NOT USED ; WD. 21 -- REGISTER BLOCK ADDRESS (DISPLACEMENT + 140000) ; BICB #ADR!SEL,U.CW2+1(R5) ;CLEAR FLAGS MOV #RETRY,RTTBL(R3);SET RETRY COUNT CALL $VOLVD ;VALIDATE VOLUME VALID BCS 10$ ;IF CS WE FAILED TST R0 ;TRANSFER FUNCTION? BMI EMUBMP ;IF MI YES TST I.PRM+2(R1) ;SIZE THE DISK? BPL 10$ ;IF PL NO CALL $RQCND ;REQUEST CONTROLLER FOR DATA TRANSFER MOV @S.KRB(R4),R2 ;RETRIEVE CSR ADDRESS MOVB U.UNIT(R5),MLCS2(R2) ;SELECT THE UNIT MOV S.PKT(R4),R1 ;RETRIEVE I/O PACKET ADDRESS MOVB #111,(R2) ;CLEAR THE DRIVE BIT #10000,MLCS2(R2);DOES THE DRIVE EXIST? BEQ 5$ ;IF EQ YES MOVB #TRE/256.,MLCS1+1(R2) ;CLEAR THE CONTROLLER MOV #IE.SZE&377,R0 ;UNABLE TO SIZE DEVICE BICB #US.VV,U.STS(R5);RESET VOLUME VALID CALL $RLCN ;RELEASE THE CONTROLLER BR 10$ ;EXIT 5$: CALL $CRPAS ;PASS CONTROLLER REGISTERS TO TASK MOV #IS.SUC&377,R0 ;SET SUCCESSFUL OPERATION BR 50$ ; 10$: CALL $IODON ;FINISH I/O BR EMINI ;GET NEXT PACKET TO PROCESS ; ; NOW REQUEST THE CONTROLLER AND DETERMINE IF THE UNIBUS ADDRESS IS ; ALREADY IN THE FORMAT FOR THE MASSBUS CONTROLLER OR THE UNIBUS MAP ; FOR 22-BIT PROCESSORS WITHOUT RH CONTROLLERS. ; EMUBMP: BITB #ADR,U.CW2+1(R5);ADDRESS BITS ALREADY SET UP? BNE EMINIO ;IF NE YES BISB #ADR,U.CW2+1(R5);SHOW ADDRESS BITS SET UP CALL $RQCND ;REQUEST CONTROLLER FOR DATA TRANSFER MOV S.KRB(R4),R1 ;RETRIEVE KRB ADDRESS BIT #FE.EXT,$FMASK ;22-BIT ADDRESSING ENABLED? BEQ 20$ ;IF EQ NO BIT #KS.MBC,K.STS(R1) ;YES, IS THIS A 22-BIT CONTROLLER? BNE 30$ ;IF NE YES CALL $STMAP ;SET UP UNIBUS MAP ADDRESS 20$: ASL U.BUF(R5) ;SHIFT BITS <4:5> TO BITS <8:9> ASL U.BUF(R5) ;... ASL U.BUF(R5) ;... ASL U.BUF(R5) ;... BIT #FE.EXT,$FMASK ;22-BIT ADDRESSING ENABLED? BEQ 30$ ;IF EQ NO CALL $MPUBM ;MAP UNIBUS TO TRANSFER ; ; CONVERT THE I/O FUNCTION CODE TO IT'S HARDWARE EQUIVALENT. ; 30$: MOV S.PKT(R4),R1 ;RETRIEVE I/O PACKET ADDRESS CMP #IO.WCK!IQ.UMD,I.FCN(R1) ;DIAGNOSTIC WRITE CHECK? BNE 40$ ;IF NE NO BISB #151,U.BUF(R5) ;YES, SET FUNCTION CODE BR 60$ ; 40$: MOV #IE.IFC&377,R0 ;ASSUME ILLEGAL FUNCTION BISB #171,U.BUF(R5) ;ASSUME READ LOGICAL FUNCTION CMPB #IO.RLB/256.,I.FCN+1(R1) ;READ LOGICAL FUNCTION? BHIS 55$ ;IF HIS FUNCTION IS LEGAL 50$: MOV @S.KRB(R4),R2 ;RETRIEVE CSR ADDRESS MOVB U.UNIT(R5),MLCS2(R2) ;SELECT DRIVE CALLR EMFIN1 ;FINISH UP 55$: BEQ 60$ ;IF EQ FUNCTION IS READ SUB #10,U.BUF(R5) ;CONVERT TO WRITE LOGICAL FUNCTION ; ; VALIDATE AND CONVERT LBN. ; 60$: CALL $BLKCK ;CHECK LOGICAL BLOCK NUMBER MOV R0,I.PRM+12(R3) ;SAVE DISK ADDRESS MOV S.KRB(R4),R1 ;RETRIEVE KRB ADDRESS MOVB K.CON(R1),R1 ;RETRIEVE CONTROLLER INDEX MUL #5,R1 ;SET UP AN INDEX INTO ... ADD #PRMSV,R1 ;... PARAMETER SAVE AREA MOV U.BUF(R5),(R1)+ ;SAVE PARAMETERS MOV U.BUF+2(R5),(R1)+ ;... MOV U.CNT(R5),(R1)+ ;... MOV I.PRM+10(R3),(R1)+ ;... MOV I.PRM+12(R3),(R1)+ ;... .DSABL LSB ; ; **-EMINIO-INTIATE AN I/O OPERATION ; ; THIS ROUTINE WILL INITIATE THE DATA TRANSFER OPERATION. AT THIS ; POINT THE CONTROLLER MUST BE REQUESTED FOR A DATA TRANSFER. ; ; INPUTS: ; ; R4=ADDRESS OF THE SCB. ; R5=ADDRESS OF THE UCB. ; EMINIO: MOV @S.KRB(R4),R2 ;GET CSR ADDRESS MOV S.PKT(R4),R1 ;GET I/O PACKET ADDRESS MOVB U.UNIT(R5),MLCS2(R2) ;SELECT UNIT ; ; DETERMINE IF DRIVE'S PORT IS SEIZED BY THIS CONTROLLER. ; CLR MLDS(R2) ;ATTEMPT TO SEIZE THE DRIVE BIT #400,MLDS(R2) ;DID THE DRIVE SEIZE? BNE 5$ ;IF NE YES MOVB #100,(R2) ;RE-ENABLE INTERRUPTS BISB #SEL,U.CW2+1(R5);SET PORT SELECT WAIT FLAG MOVB S.ITM(R4),S.CTM(R4) ;SET CURRENT DEVICE TIMEOUT COUNT CALLR $RLCN ;RELEASE CONTROLLER AND EXIT ; ; LOAD CONTROLLER REGISTERS FOR DATA TRANSFER. ; 5$: MOV #TRE!11,(R2) ;CLEAR CONTROLLER AND DRIVE ERRORS ADD #MLCS2,R2 ;POINT TO SECOND CSR MOV I.PRM+12(R1),-(R2) ;INSERT DISK ADDRESS MOV U.BUF+2(R5),-(R2) ;INSERT BUFFER ADDRESS MOV U.CNT(R5),-(R2) ;INSERT NUMBER OF BYTES TO TRANSFER ROR (R2) ;CONVERT TO WORD COUNT NEG (R2) ;MAKE NEGATIVE WORD COUNT TST -(R2) ;POINT TO CSR REGISTER ; ; TEST FOR DRIVE NOT READY CONDITIONS. ; MOV #IE.DNR&377,R0 ;ASSUME DRIVE NOT READY MOV MLDS(R2),R3 ;GET CONTENTS OF DRIVE STATUS REGISTER COM R3 ;COMPLEMENT STATUS BIT #10200,R3 ;DRIVE READY AND ON-LINE? BEQ 20$ ;IF EQ YES BITB #US.SPU,U.STS(R5) ;IS DRIVE 'SPINNING UP'? BEQ 10$ ; IF EQ NO BITB #US.VV,U.STS(R5) ;WAS THE VOLUME PREVIOUSLY MOUNTED? BEQ EMPWF1 ;IF EQ NO BR EMPWF0 ;YES, WAIT FOR IT TO 'SPIN UP' 10$: BITB #IQ.UMD,I.FCN(R1) ;DIAGNOSTIC OPERATION BEQ 15$ ;IF EQ NO CALLR EMDIAG ;LOG DIAGNOSTIC DRIVE NOT READY 15$: CALL $DVERR ;LOG DEVICE TIMEOUT ERROR CALLR EMFIN ;FINISH UP 20$: BICB #US.SPU,U.STS(R5) ;RESET DRIVE 'SPINNING UP' BICB #S3.SPU,S.ST3(R4) ;CLEAR PORT 'SPINNING UP' FLAGS MOV S.KRB(R4),R3 ;GET CURRENT KRB ADDRESS MOV R3,R1 ;COPY KRB ADDRESS ; ; START THE DATA TRANSFER OPERATION. ; MTPS #PR5 ;;;DISABLE INTERRUPTS BIT #FE.EXT,$FMASK ;;;22-BIT ADDRESSING ENABLED? BEQ 30$ ;;;IF EQ NO BIT #KS.MBC,K.STS(R3) ;;;IS THIS A 22-BIT CONTROLLER? BEQ 30$ ;;;IF EQ NO ADD K.OFF(R3),R1 ;;;POINT TO UCB TABLE MOV KE.RHB(R1),R1 ;;;RETRIEVE RHBAE OFFSET ADD R2,R1 ;;;FORM AN I/O PAGE ADDRESS MOVB U.BUF+1(R5),(R1);;;SET MEMORY EXTENSION BITS MOVB U.BUF(R5),(R2) ;;;START FUNCTION BR 40$ ;;; 30$: MOV U.BUF(R5),(R2) ;;;START FUNCTION 40$: CLR S.FRK+2(R4) ;;;INIT FORK INTERLOCK MOVB S.ITM(R4),S.CTM(R4) ;;;SET TIMEOUT COUNT BIS #KS.DIP,K.STS(R3) ;;;SET DATA TRANSFER IN PROGRESS BIS #S2.ACT,S.ST2(R4) ;;;SHOW I/O IS ACTIVE MTPS #0 ;ALLOW INTERRUPTS ; ; CANCEL I/O OPERATION IS A NOP FOR FILE STRUCTURED DEVICES. ; EMCAN: RETURN ;NOP ;+ ; POWERFAIL IS HANDLED VIA THE DEVICE TIMEOUT FACILITY AND ; CAUSES NO IMMEDIATE ACTION ON THE UNIT. ;- EMPWF: TSTB S.STS(R4) ;IS THIS UNIT CURRENTLY BUSY? BEQ EMPWF2 ;IF EQ NO EMPWF0: MOVB #4,S.STS(R4) ;WAIT A MAXIMUM OF 8 SECONDS EMPWF1: MOVB S.ITM(R4),S.CTM(R4) ;2 SECONDS AT A TIME EMPWF2: BISB #US.SPU,U.STS(R5) ;SET UNIT 'SPINNING UP' EMPWF3: CALLR $RLCN ;RELEASE CONTROLLER (IF NECESSARY) ;+ ; **-$EMINT-RH11-ML11 MEMORY SYSTEM CONTROLLER INTERRUPTS ; INTERRUPT SERVICE ROUTINE ;- $EMINT::BR EMFRK ;;;ENTRY POINT FOR DATA TRANSFERS TST S.FRK+2(R4) ;;;ARE INTERRUPTS ALLOWED? BNE EMCAN ;;;IF NE NO CALL $FORK ;;;CREATE A SYSTEM PROCESS EMFRK: CALL $RQCND ;REQUEST CONTROLLER FOR DATA TRANSFER BITB #SEL,U.CW2+1(R5);WAITING FOR PORT TO SELECT? BEQ 5$ ;IF EQ NO BICB #SEL,U.CW2+1(R5);CLEAR PORT SELECT WAIT FLAG JMP EMINIO ;YES, GO DO THE TRANSFER 5$: MOV S.KRB(R4),R3 ;GET CURRENT KRB ADDRESS MOVB K.CON(R3),R3 ;RETRIEVE CONTROLLER INDEX MOV U.SCB(R5),R4 ;GET ADDRESS OF SCB MOV #IS.SUC&377,R0 ;ASSUME SUCCESSFUL TRANSFER MOV @S.KRB(R4),R2 ;GET CSR ADDRESS MOVB U.UNIT(R5),MLCS2(R2) ;SELECT UNIT TSTB S.STS(R4) ;IS THIS UNIT BUSY? BNE 15$ ;IF NE YES CLR S.FRK+2(R4) ;RESET FORK INTERLOCK MOV #TRE!11,(R2) ;CLEAR CONTROLLER AND DRIVE BIT #S2.MAD,S.ST2(R4) ;MULTI-ACCESS DEVICE? BNE 10$ ;IF NE YES MOVB #100,(R2) ;NO, JUST RE-ENABLE INTERRUPTS BR EMPWF3 ;RELEASE CONTROLLER AND EXIT 10$: MOVB #113,(R2) ;RELEASE THE DRIVE BISB #S3.DRL,S.ST3(R4) ;SHOW DUAL ACCESS UNIT RELEASED BR EMPWF3 ;RELEASE CONTROLLER AND EXIT ; ; THE UNIT WAS BUSY. NOW CHECK FOR ERRORS. ; 15$: BITB #US.SPU,U.STS(R5) ;ARE WE 'SPINNING UP'? BNE EMREST ;IF NE YES MOV S.PKT(R4),R1 ;GET I/O PACKET ADDRESS BITB #IQ.UMD,I.FCN(R1) ;DIAGNOSTIC FUNCTION EXECUTED? BNE EMDIAG ;IF NE YES BIT #60000,(R2) ;ANY ERRORS? BEQ EMWCHK ;IF EQ NO MOV MLWC(R2),R0 ;GET NEGATIVE WORDS REMAINING ASL R0 ;CONVERT TO NEGATIVE BYTES ADD U.CNT(R5),R0 ;CALCULATE BYTES ACTUALLY TRANSFERRED SUB #512.,R0 ;SUBTRACT OUT BLOCK IN ERROR BLE 20$ ;IF LE NO GOOD BYTES TRANSFERRED BIT #S2.EIP,S.ST2(R4) ;ERROR ALREADY IN PROGRESS BEQ 20$ ;IF EQ NO ; ; WE GOT AN ERROR BUT SOME GOOD DATA WAS TRANSFERRED. THIS ; INDICATES THAT WE RECOVERED FROM THE PREVIOUS ERROR. ; CALL EMCALC ;CALCULATE NEW DISK PARAMETERS MOV R2,-(SP) ;SAVE CSR ADDRESS MOVB RTTBL(R3),R2 ;GET FINAL ERROR RETRY COUNT BIS #RETRY*256.,R2 ;MERGE STARTING RETRY COUNT MOV #IS.SUC&377,R0 ;THIS RECOVERY WAS SUCCESSFUL CALL $FNERL ;FINISH ERROR LOGGING PROCESS MOV #RETRY,RTTBL(R3);SET INITIAL RETRY COUNT MOV (SP)+,R2 ;RESTORE CSR ADDRESS 20$: CALL $DVERR ;LOG DEVICE ERROR MOV #IE.WCK&377,R0 ;ASSUME WRITE CHECK ERROR BIT #40000,MLCS2(R2) ;WRITE CHECK ERROR? BNE EMRTRY ;IF NE YES MOV #IE.VER&377,R0 ;ASSUME UNRECOVERABLE ERROR MOV MLER(R2),R1 ;GET CONTENTS OF ERROR REGISTER BIT #43007,R1 ;HARD ERROR? BNE 30$ ;IF NE YES BIT #14000,MLCS2(R2);NEM OR NED? BNE 30$ ;IF NE YES TST MLCS2(R2) ;DATA LATE ERROR? BPL EMRTRY ;IF PL NO CALL EMCALC ;YES, CALCULATE NEW PARAMETERS BR EMRTRY ;RETRY FROM BLOCK IN ERROR 30$: BIT #4000,R1 ;WRITE LOCK ERROR? BEQ EMFIN ;IF EQ NO MOV #IE.WLK&377,R0 ;SET WRITE LOCK ERROR BR EMFIN ;FINISH I/O ; ; DEVICE TIMEOUT RESULTS IN THE CURRENT OPERATION BEING REPEATED ; UNLESS THE REQUEST WAS DIAGNOSTIC. TIMEOUTS ARE USUALLY CAUSED ; BY POWERFAILURE BUT MAY ALSO BE THE RESULT OF A HARDWARE FAILURE. ; EMOUT: BITB #US.SPU,U.STS(R5) ;;;IS DRIVE 'SPINNING UP'? BEQ 10$ ;;;IF EQ NO DECB S.STS(R4) ;;;HAVE WE WAITED ENOUGH YET? BEQ 10$ ;;;IF EQ YES MTPS #0 ;;;ALLOW INTERRUPTS CALL $RQCND ;REQUEST CONTROLLER FOR TRANSFER BR EMREST ;RETRY ENTIRE OPERATION 10$: INCB S.STS(R4) ;;;LEAVE CONTROLLER BUSY BICB #US.SPU,U.STS(R5) ;;;RESET DRIVE 'SPINNING UP' MTPS #0 ;;;ALLOW INTERRUPTS CALL $RQCND ;REQUEST CONTROLLER FOR TRANSFER MOV S.KRB(R4),R2 ;GET CURRENT KRB ADDRESS MOVB K.CON(R2),R3 ;RETRIEVE CONTROLLER INDEX MOV (R2),R2 ;RETRIEVE CSR ADDRESS MOVB U.UNIT(R5),MLCS2(R2) ;SELECT UNIT CALL $DVTMO ;LOG DEVICE TIMEOUT BITB #SEL,U.CW2+1(R5);WAITING FOR PORT TO SELECT? BNE EMFIN1 ;IF NE YES, WE DIDN'T GET IT BCC EMRTRY ;IF CC, TIMEOUT DURING NORMAL FUNCTION EMDIAG: CALL $CRPAS ;PASS CONTROLLER REGISTERS TO TASK BR EMFIN ;DIAGNOSTIC PROCESSING COMPLETE ; ; RETRY THE CURRENT OPERATION. ; EMRTRY: MOV S.PKT(R4),R1 ;GET I/O PACKET ADDRESS BITB #IQ.X,I.FCN(R1) ;INHIBIT RETRIES? BNE EMFIN ;IF NE YES DEC RTTBL(R3) ;RETRY FUNCTION? BLE EMFIN ;IF LE NO EMREST: MOVB #111,(R2) ;CLEAR THE DRIVE CALLR EMUBMP ;RESTART OPERATION ; ; TEST FOR WRITE CHECK OPERATION. ; EMWCHK: BITB #IO.WLC&377,I.FCN(R1) ;WRITE FOLLOWED BY WRITE CHECK? BNE 10$ ;IF NE YES BITB #US.WCK,U.STS(R5) ;WRITE CHECK ENABLED BY MCR? BEQ EMFIN ;IF EQ NO 10$: MOVB U.BUF(R5),R1 ;GET LAST FUNCTION CMPB #171,R1 ;WAS IT A READ? BEQ EMFIN ;IF EQ YES CMPB #161,R1 ;WAS LAST FUNCTION A WRITE? BNE EMFIN ;IF NE NO MOV #RETRY,RTTBL(R3);REINITIALIZE RETRY COUNT MOV S.PKT(R4),R1 ;RETRIEVE I/O PACKET ADDRESS MUL #5,R3 ;FORM AN INDEX INTO ... ADD #PRMSV,R3 ;... PARAMETER SAVE AREA MOV (R3)+,U.BUF(R5) ;RESTORE PARAMETERS MOV (R3)+,U.BUF+2(R5) ;... MOV (R3)+,U.CNT(R5) ;... MOV (R3)+,I.PRM+10(R1) ;... MOV (R3)+,I.PRM+12(R1) ;... MOVB #151,U.BUF(R5) ;SET WRITE CHECK FUNCTION BR EMREST ;START WRTIE CHECK OPERATION ; ; **-EMFIN-FINISH I/O OPERATION ; ; THIS ROUTINE WILL SET THE ACTUAL BYTES TRANSFERRED PARAMETER, THE ; ERROR LOGGING RETRY COUNTS AND CALL $IODON. A CHECK WILL BE MADE ; FOR ANY PENDING ATTENTIONS AND THE CONTROLLER WILL BE RELEASED. ; ; INPUTS: ; ; R0=SUCCESS/ERROR CODE ; R2=ADDRESS OF CONTROLLER CSR ; R4=ADDRESS OF THE SCB ; R5=ADDRESS OF THE UCB ; EMFIN: MOV MLWC(R2),R1 ;GET WORDS REMAINING TO TRANSFER ASL R1 ;CONVERT TO BYTES LEFT TO TRANSFER ADD U.CNT(R5),R1 ;CALCULATE BYTES ACTUALLY TRANSFERRED EMFIN1: MOVB #11,(R2) ;CLEAR THE DRIVE MOV #TRE,(R2) ;NOW CLEAR THE DRIVE MOV S.KRB(R4),R3 ;GET CURRENT KRB ADDRESS BICB #SEL,U.CW2+1(R5);CLEAR PORT SELECT WAIT FLAG 10$: TSTB MLAS(R2) ;ANY ATTENTIONS PENDING? BEQ 20$ ;IF EQ NO BISB #100,(R2) ;RE-DISPATCH TO INTERRUPT HANDLER BR 10$ ;TRY AGAIN 20$: BIT #S2.MAD,S.ST2(R4) ;DUAL ACCESS DEVICE? BEQ 30$ ;IF EQ NO BITB #S3.NRL,S.ST3(R4) ;SHOULD WE RELEASE THE DRIVE? BEQ 35$ ;IF EQ YES 30$: MOVB #100,(R2) ;RE-ENABLE INTERRUPTS BR 40$ ; 35$: BISB #S3.DRL,S.ST3(R4) ;SHOW DUAL ACCESS UNIT RELEASED MOVB #113,(R2) ;RE-ENABLE INTERRUPTS AND RELEASE DRIVE 40$: MOVB K.CON(R3),R3 ;RETRIEVE CONTROLLER INDEX MOVB RTTBL(R3),R2 ;GET FINAL ERROR RETRY COUNT BIS #RETRY*256.,R2 ;MERGE STARTING RETRY COUNT CALL $RLCN ;RELEASE CONTROLLER CALL $IODON ;FINISH I/O OPERATION JMP EMINI ;PROCESS NEXT REQUEST ; ; THE TRANSFER STOPPED DUE TO A RETRYABLE ERROR CONDITION. WE ; WILL NOW BACKUP THE WORD COUNT, BUS ADDRESS AND TRACK/SECTOR ; ADDRESS BY ONE BLOCK AND RETRY THE TRANSFER FROM THIS POINT. ; THIS IS DONE TO PREVENT THE ERROR CONDITION FROM RECURRING DUE ; TO A LONG TRANSFER. ; EMCALC: MOV MLWC(R2),R0 ;GET NEGATIVE WORDS REMAINING BNE 10$ ;IF NE WE HAD A PARTIAL TRANSFER MOV #-1,R0 ;DLT ON LAST WORD, FAKE PARTIAL XFR 10$: ASL R0 ;CONVERT TO NEGATIVE BYTES ADD U.CNT(R5),R0 ;CALCULATE BYTES ACTUALLY TRANSFERRED BIC #777,R0 ;GET BLOCKS ACTUALLY TRANSFERRED SUB R0,U.CNT(R5) ;REDUCE BYTES REMAINING TO TRANSFER BEQ 30$ ;IF EQ NO MORE BYTES TO TRANSFER ADD R0,U.BUF+2(R5) ;UPDATE STARTING BUFFER ADDRESS ADCB U.BUF+1(R5) ;AND THE MEMORY EXTENSION BITS BIT #FE.EXT,$FMASK ;IS 22-BIT ADDRESSING ENABLED? BEQ 15$ ;IF EQ NO MOV S.KRB(R4),R1 ;RETRIEVE THE KRB ADDRESS BIT #KS.MBC,K.STS(R1) ;IS THIS A 22-BIT MASSBUS DEVICE? BNE 15$ ;IF NE YES ADD K.OFF(R1),R1 ;POINT TO UMR AREA+2 ADD R0,-(R1) ;CALCULATE NEW REAL ADDRESS ADCB -(R1) ;... 15$: MOV S.PKT(R4),R1 ;RETRIEVE I/O PACKET ADDRESS SWAB R0 ;GET BLOCKS*2 TRANSFERRED CLC ;CLEAR CARRY FOR ROTATE ROR R0 ;GET BLOCKS TRANSFERRED 20$: ADD R0,I.PRM+12(R1) ;UPDATE DISK ADDRESS RETURN ; 30$: ADD R0,U.CNT(R5) ;YES, BACKUP BYTES TO TRANSFER RETURN ; .END